﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using System.Net;
using System.IO;
using System.Text;
using NLog;

namespace Aandelendelen.Payment
{
	public abstract class Ideal
	{
		protected static Logger logger = LogManager.GetCurrentClassLogger();

		private bool testMode = false;

		protected bool error = false;
		private string errorMessage = "";

		protected string partnerId; //alleen mollie

		protected readonly string banksUrl = "https://www.targetpay.com/ideal/getissuers.php?format=xml";
		protected readonly string checkUrl = "https://www.targetpay.com/ideal/check";
		protected readonly string fetchUrl = "https://www.targetpay.com/ideal/start";

		protected readonly string phoneGetUrl = "http://api.targetpay.nl/payment/startpayment.asp";

		public Ideal(string partnerId)
		{
			this.partnerId = partnerId;
		}

		public Ideal(string partnerId, bool testMode)
			: this(partnerId)
		{
			this.testMode = testMode;
		}

		protected virtual void ProcessTargetPayResponse(string response)
		{
			throw new NotImplementedException("ProcessTargetPayResponse");
		}

		protected virtual void ProcessResponse(XmlDocument doc)
		{
			throw new NotImplementedException("ProcessResponse");
		}

		protected void ProcessRequest(string url)
		{
			this.ProcessRequest(url, null);
		}

		protected void ProcessRequest(string url, Dictionary<string, string> args)
		{
			try
			{
				Uri uri = new Uri(url, UriKind.Absolute);
				bool q = true;
				if (string.IsNullOrEmpty(uri.Query))
				{
					q = false;
				}
				StringBuilder fullUrl = new StringBuilder(url, 256);

				if (args != null)
				{
					bool first = true;
					foreach (string key in args.Keys)
					{
						if (first && q == false)
						{
							fullUrl.Append("?");
							first = false;
						}
						else
							fullUrl.Append("&");

						fullUrl.Append(key);
						fullUrl.Append("=");
						fullUrl.Append(Uri.EscapeDataString(args[key]));
					}
				}

				if (url.Contains("targetpay"))
				{
					logger.Debug("Calling {0}", fullUrl.ToString());
					string response = this.GetStringResponse(fullUrl.ToString());
					this.ProcessTargetPayResponse(response);
				}
				else
				{
					XmlDocument doc = this.GetResponse(fullUrl.ToString());

					this.ProcessResponse(doc);
				}
			}
			catch (Exception e)
			{
				this.error = true;

				this.errorMessage = e.Message;

				logger.ErrorException("Ideal.ProcessRequest", e);
			}
		}

		protected void ThrowXmlException(XmlDocument doc)
		{
			throw new XmlException(doc.InnerXml);
		}

		public bool TestMode
		{
			get { return this.testMode; }
			set { this.testMode = value; }
		}

		public bool Error
		{
			get { return this.error; }
		}

		public string ErrorMessage
		{
			get { return this.errorMessage; }
		}

		private string GetStringResponse(string url)
		{
			HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

			// Set some reasonable limits on resources used by this request
			request.MaximumAutomaticRedirections = 4;
			request.MaximumResponseHeadersLength = 4;
			// Set credentials to use for this request.
			request.Credentials = CredentialCache.DefaultCredentials;
			HttpWebResponse response = (HttpWebResponse)request.GetResponse();

			// Get the stream associated with the response.
			Stream receiveStream = response.GetResponseStream();

			// Pipes the stream to a higher level stream reader with the required encoding format. 
			StreamReader readStream = new StreamReader(receiveStream, System.Text.Encoding.UTF8);

			string htmlResponse = readStream.ReadToEnd();

			readStream.Close();
			response.Close();

			return htmlResponse;
		}

		private XmlDocument GetResponse(string url)
		{
			if (this.testMode)
				url += "&testmode=true";

			XmlTextReader reader = new XmlTextReader(url);
			XmlDocument doc = new XmlDocument();

			doc.Load(reader);

			reader.Close();

			/***************
			 * Uncomment the following line, if you would like to view the xml structure returned by Mollie.
			 ***************/
			//doc.Save(HttpContext.Current.Server.MapPath("/App_Data/IdealLog.xml"));

			return doc;
		}
	}

}